home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Graphics⁄Sound
/
Contours source
/
fractal.c
next >
Wrap
C/C++ Source or Header
|
1986-04-19
|
16KB
|
579 lines
/*
** Three-dimensional Fractal Contour Map generator.
** Program originally in MicroSoft BASIC for the Macintosh.
** Taken from July 1985 Creative Computing.
**
** Used as an example BASIC-C comparison.
*/
#include <memory.h>
#include <quickdraw.h>
#include <font.h>
#include <window.h>
#include <osutil.h>
#include <menu.h>
#include <event.h>
#include <textedit.h>
#include <dialog.h>
#include <desk.h>
#include <control.h>
#include <toolutil.h>
#define watchCursor 4 /* Should be in TOOLUTIL.H but isn't. JEC */
#include <resource.h>
#include <stdio.h>
#include "fractal.h"
GrafPtr screenport; /* A port for the whole screen. */
WindowPtr mywindow; /* Our one window. */
WindowRecord wrecord; /* Storage for window record. */
MenuHandle mymenus[LASTMENU + 1]; /* Our menus. */
PicHandle thepicture;
BitMap savepix; /* Storage for the update bitmap. */
EventRecord myevent;
WindowPtr whichwindow; /* Points to window of MouseDown. */
int windowcode; /* What mouse was in when event posted. */
Boolean userdone; /* True when user wants to exit program. */
int ispicture; /* True if there is a Picture definition of the
contour available. */
int isbitmap; /* True if there is a bitmap copy of the contour
available. Saves time in update events. */
int usebitmap; /* True if the bitmap should be used to update. */
main() {
setup();
maineventloop();
}
/*############################ MainEventLoop ########################*/
maineventloop() {
FlushEvents(everyEvent, 0);/* discard leftover events */
/* get next event, and handle it appropriately, until user QUITs */
userdone = 0;
do {
SystemTask(); /* Handle desk accessories. */
if (GetNextEvent(everyEvent, &myevent)) {
/* get event; if for us... */
switch (myevent.what) {/* handle each kind of event */
case mouseDown: /* find out what window the mouse went
down in, and where in it */
windowcode = FindWindow(pass(myevent.where), &whichwindow);
switch (windowcode) {
/* handle mouse-down for each place */
case inSysWindow:
/* handle the desk accessories */
SystemClick(&myevent, whichwindow);
break;/* insyswindow */
case inMenuBar: /* handle the command */
userdone = docommand(MenuSelect(&myevent.where));
break;/* inmenubar */
case inDrag: /* No Drag Region, treat as Content. */
case inContent:
/* includes inGrow if window inactive.
Activate window */
if (whichwindow == mywindow)
/* make sure it's for mine */
if (whichwindow != FrontWindow())
SelectWindow(whichwindow);
/* make it active */
break;
case inGrow: /* No Grow Region */
break;
case inGoAway:
/* we don't have a GoAway region */
break;
}
break; /* switch */
case keyDown:
case autoKey: /* if command key, pass the char to
MenuKey */
if ((myevent.modifiers & cmdKey) != 0)
userdone = docommand(MenuKey((char) (myevent.message & charCodeMask)));
case updateEvt: /* if it's for our window, update it */
if ((WindowPtr) (myevent.message) == mywindow)
updatewindow(mywindow);
/* redraw the window contents */
break;
case activateEvt:
/* if for our window, set port as nec. */
if ((WindowPtr) (myevent.message) == mywindow) {
/* my window */
if (myevent.modifiers & 1) {
/* odd means an activate event */
SetPort(mywindow);
/* activate evt: work in our own port */
DisableItem(mymenus[EDITMENU], 0);
EnableItem(mymenus[FILEMENU], 0);
EnableItem(mymenus[SETUPMENU], 0);
DrawMenuBar();
}
else {
SetPort(screenport);
/* deactivate evt: our port is gone; keep
port from dangling */
EnableItem(mymenus[EDITMENU], 0);
DisableItem(mymenus[FILEMENU], 0);
DisableItem(mymenus[SETUPMENU], 0);
DrawMenuBar();
}
} break;
}
}
} while (userdone == 0);
}
/*
handle a command given through a menu selection
############################ DoCommand ##############################
We carry out the command indicated by mResult.
If it was Quit, we return true, else false. Since the menu was
highlighted by MenuSelect, we must finish by unhighlighting it
to indicate we're done.
*/
int docommand(mresult)
long mresult;
{
int refnum;
int themenu,
theitem;
char name[255];
GrafPtr saveport; /* for saving current port in when opening
a desk accessory */
int returns;
returns = 0; /* assume Quit not selected */
themenu = HiWord(mresult); /* get the menu selected */
theitem = LoWord(mresult); /* ... and the item of that menu */
switch (themenu) {
case 0:
break; /* user made no selection; do nothing */
case APPLEMENU:
if (theitem == 1) /* Tell about FracCont */
report();
else { /* run a desk accessory; make sure port is
preserved */
GetPort(&saveport);
GetItem(mymenus[APPLEMENU], theitem, name);
/* get name */
refnum = OpenDeskAcc(name);/* run the desk accessory */
SetPort(saveport);
}
break;
case FILEMENU:
switch (theitem) {
case ANOTHER: /* New Surface */
calcsurf(contlevl);
InvalRect(&mywindow -> portRect);
usebitmap = FALSE;
break;
case SAVEPAINT: /* Not yet. */
break;
case IQUIT:
returns = 1;/* Quit */
break;
} /* FILEMENU case */
break;
case SETUPMENU:
switch (theitem) {
case SETUP: /* Setup */
setupDlg();
break;
} /* SETUPMENU case */
} /* menu case */
HiliteMenu(0); /* turn off hilighting on the menu just
used */
return (returns);
} /* DoCommand */
/*############################ Setup Dialog ######################*/
TerrainBTN(ptr, oncontrl, offcontrl)
DialogPtr ptr;
int oncontrl, offcontrl;
{
int itemtype;
ControlHandle item;
Rect itembox;
GetDItem(ptr, offcontrl, &itemtype, &item, &itembox);
SetCtlVal(item, 0); /* Turn off old Default Button. */
GetDItem(ptr, oncontrl, &itemtype, &item, &itembox);
SetCtlVal(item, 1); /* Turn on Default Button. */
return oncontrl;
}
setupDlg() /* Do the SETUP menu dialog. */
{
int newtype; /* Selected Contour type. */
int newlevel; /* Selected Level of Detail. */
int userexit;
int doanother; /* True if we need to recalc. */
int itemhit; /* Item # of punched button (or whatever) */
DialogPtr setupptr;
char asciibufr[10];
int itemtype;
ControlHandle item;
Rect itembox;
newtype = conttype; /* SETUPMTN, SETUPHIL, or SETUPWATR */
newlevel = contlevl;
doanother = FALSE;
setupptr = GetNewDialog(STPDLGID, NULL, (long) -1);
TerrainBTN(setupptr, conttype, conttype);
asciibufr[1] = newlevel + '0'; /* Only good for 0..9, OK here. */
asciibufr[0] = 1;
GetDItem(setupptr, SETUPLEVL, &itemtype, &item, &itembox);
SetIText(item, asciibufr);
SelIText(setupptr, SETUPLEVL, 0, 100); /* Hilite text field. */
userexit = FALSE;
do {
ModalDialog(NULL, &itemhit);
/* carry out dialog; NIL => no FilterProc;
return item Hit when done */
GetDItem(setupptr, SETUPLEVL, &itemtype, &item, &itembox);
GetIText(item, asciibufr); /* Get Level field */
if (asciibufr[0] != 1) /* Only good for 1..9, OK here. */
newlevel = 100;
else
newlevel = asciibufr[1] - '0';
if (newlevel < 1 || newlevel > MAXLEVEL)
SelIText(setupptr, SETUPLEVL, 0, 100); /* Hilite text field. */
if (itemhit == SETUPMTN)
newtype = TerrainBTN(setupptr, itemhit, newtype);
if (itemhit == SETUPHIL)
newtype = TerrainBTN(setupptr, itemhit, newtype);
if (itemhit == SETUPWATR)
newtype = TerrainBTN(setupptr, itemhit, newtype);
if (itemhit == SETUPOK && ((newlevel > 0) & (newlevel <= MAXLEVEL))) {
if (conttype != newtype || contlevl != newlevel) {
if (contlevl != newlevel)
doanother = TRUE;
InvalRect(&mywindow -> portRect);
usebitmap = FALSE;
}
contlevl = newlevel;
conttype = newtype;
userexit = TRUE;
}
if (itemhit == SETUPCAN)
userexit = TRUE;
} while (!userexit);
DisposDialog(setupptr); /* release storage and remove dialog from
screen */
if (doanother)
calcsurf(newlevel); /* Removes dialog first. */
} /* Setup */
/*
############################ Report #################################
*/
report()
{
int itemhit;
DialogPtr reportptr;
reportptr = GetNewDialog(INFOSCR1, NULL, (long) -1);
/* Get from Resource file; NIL => use heap
storage; -1 => make dlg frontmost */
ModalDialog(NULL, &itemhit);
/* carry out dialog; NIL => no FilterProc;
return item Hit when done */
DisposDialog(reportptr); /* release storage and remove dialog from
screen */
if (itemhit == INFOMORE) {
reportptr = GetNewDialog(INFOSCR2, NULL, (long) -1);
ModalDialog(NULL, &itemhit);
DisposDialog(reportptr);
}
}
/*
SetUps for handling memory
########################## SetUpMemory ############################
*/
setupmemory() {
#define maxStackSize 8192 /* max size of stack; the heap gets the
rest */
typedef long *lomemptr; /* a pointer to low memory locations */
lomemptr nilptr; /* will have value NIL */
lomemptr stackbaseptr; /* points to current stack base */
/*
If you define a GrowZone function to handle bad memory problems,
you should define it at the top level (not nested), and set it
here. We don't.
*/
/* SetGrowZone(&mygrowzone); */
/*
Place a longint -1 (an odd and therefore illegal address) in the
memory location that would be referenced by an accidentally-NULL
handle, so the error will be caught at handle-reference time (as
an Address error, ID=02) instead of later on.
*/
nilptr = NULL;
*nilptr = -1;
/*
If you needed to use an Application heap limit other than the
default (which allows 8K for the stack), you'd set it here,
possible using this technique of explicitly specifying the maximum
stack size and allocating the rest to the heap. Should be
independent of memory size. */
stackbaseptr = (lomemptr) 0x908;
/* CurStackBase from Tlasm/sysequ.text */
SetApplLimit((Ptr) (*stackbaseptr - maxStackSize));
/*
Expand the application heap zone to its maximum size, without
purging any purgeable resources. This saves memory compactions
and heap expansions later.
*/
MaxApplZone();
/*
get plenty of master pointers now; if we let the Memory Manager
allocate them as needed, they'd form non-relocatable islands in
the heap.
*/
MoreMasters();
MoreMasters();
} /* SetUpMemory */
/*
############################ SetUpMenus #############################
Once-only initialization for menus
We read in all menus from the resource file, and install them,
and all desk accessories (drivers).
*/
setupmenus() {
int i;
for (i = 1; i <= LASTMENU; i++)/* get all my menus in */
mymenus[i] = GetMenu(i);/* use the fact that our menu ID's start
at 1 */
AddResMenu(mymenus[APPLEMENU], 'DRVR');
/* pull in all desk accessories */
for (i = 1; i <= LASTMENU; i++)
InsertMenu(mymenus[i], 0);/* insert menus; 0 => put at end */
DrawMenuBar();
}
/*
body of SetUp
Once-only initialization.
############################ SetUp ##############################
Initialize our program. It seems best to handle:
Memory inits first, ToolBox inits second, then the program variables'
inits. Note that the order of inits is important; see "Using the
Dialog Manager" in the Dialog Mgr section.
*/
setup() {
char *ctop();
setupmemory(); /* init memory layout and protection */
/* init QuickDraw, and everybody else */
InitGraf(&thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(NULL); /* NULL => no Restart proc; see Dialog Mgr
and System Error Handler */
InitCursor();
/*
Init the system event mask, in case the previous program left
it in a bad state. If you set it non-standard here, FIX IT
BEFORE EXITING, because the Finder (1.1g) does NOT set it.
*/
SetEventMask(everyEvent - keyUpMask);/* standard setting */
/*
Get the port which is the whole screen, to use when deactivating
our window. This prevents the current grafPort pointer from
ever dangling.
*/
GetWMgrPort(&screenport); /* get whole screen port that window mgr
uses */
SetPort(screenport); /* and start off with it */
/*
get window: use wRecord storage. Port is set to that of the
new window.
GetNewWindow posts an update event for the new window,
so it will be redrawn right away.
*/
#ifdef DEVELOP
OpenResFile(ctop(DEVELOP));
#endif
mywindow = GetNewWindow(WINDOWID, &wrecord, (long) -1);
/* -1 => frontmost window */
/* pull in and set up our menus */
setupmenus();
CouldDialog(STPDLGID); /* Preload the Setup Dialog. */
conttype = DEFLTTYP; /* Default style */
contlevl = DEFLTLEV; /* Default Level */
isbitmap = FALSE;
/* Allocate the data array. */
points = NewPtr((long) XDIM*YDIM*(sizeof(int))); /* Non-reloc, but so what. */
calcsurf(contlevl); /* Do at least one first. */
}
/*
Update the contents of the given window
############################ UpdateWindow ##########################
This is our response to receipt of an update event for myWindow.
Since the window is likely to be inactive, the current grafPort
will be elsewhere. We must change it for drawing, yet leave it
as it was.
*/
updatewindow(awindow)
WindowPtr awindow;
{
GrafPtr saveport; /* to save and restore the old port */
BeginUpdate(awindow); /* reset ClipRgn etc to only redraw what's
necessary. */
GetPort(&saveport); /* don't trash the port; we might be
updating an inactive window */
SetPort(awindow); /* work in the specified window */
drawwindow(); /* redraw contents of window */
SetPort(saveport); /* all nice and tidy as before */
EndUpdate(awindow);
} /* UpdateWindow */
/*
Redraw my window
############################ DrawWindow #############################
We draw all the contents of our one window, myWindow.
*/
drawwindow()
{
/* Possibly save the drawing contents in a picture. This will allow
much faster update events than calling plotdata() repeatedly.
This is only to speed up Desk Accessory movement and the
re-painting after the Options Dialog is removed. */
CursHandle ticktock;
ticktock = GetCursor(watchCursor);
if (ticktock)
SetCursor(*ticktock); /* Show watch (wait) */
if (usebitmap) {
CopyBits(&savepix, &mywindow->portBits,
&savepix.bounds, &mywindow->portRect,
srcCopy, 0L);
}
else {
if (isbitmap)
DisposPtr(savepix.baseAddr);
savepix.bounds.top = mywindow->portRect.top;
savepix.bounds.bottom = mywindow->portRect.bottom;
savepix.bounds.left = mywindow->portRect.left;
savepix.bounds.right = mywindow->portRect.right;
savepix.rowBytes = mywindow->portBits.rowBytes;
savepix.baseAddr = NewPtr((long) savepix.rowBytes *
(savepix.bounds.bottom - savepix.bounds.top));
EraseRect(&mywindow->portRect);
plotdata();
CopyBits(&mywindow->portBits, &savepix,
&mywindow->portRect, &savepix.bounds,
srcCopy, 0L);
isbitmap = usebitmap = TRUE;
}
#ifdef not_defined
if (ispicture)
KillPicture(thepicture);
thepicture = OpenPicture(&mywindow -> portRect);
ShowPen(); /* We want the picture shown while being drawn. */
EraseRect(&mywindow -> portRect);
plotdata();
HidePen(); /* Balance the ShowPen() above. */
ClosePicture();
ispicture = TRUE;
#endif
InitCursor();
} /* DrawWindow */
/*
* The following routine was used while debugging and testing the program.
* The routine is called just like "printf()", but the output is
* directed to the printer port. Use -7 for the modem port. The
* port must already be opened. Use MIXCROOT and do a 2> .b(a)out
* to easily do this.
*/
#ifdef DEBUG
debug(fmt, arg)
char *fmt;
unsigned arg;
{
int put();
format(put, fmt, &arg);
}
put(c)
char c;
{
long i;
i = 1;
if (c=='\n')
put('\r');
FSWrite(DEBUG, &i, &c);
if (c=='\n')
for (i=2000; i; i--)
;
}
#endif